/*=+--+=#=+--     Unmanned Aerial System Management Software      --+=#=+--+=#*\
|          Copyright (C) 2011 Regents of the University of Colorado.           |
|                             All Rights Reserved.                             |

     This program is free software: you can redistribute it and/or modify
     it under the terms of the GNU General Public License version 2 as
     published by the Free Software Foundation.

     This program is distributed in the hope that it will be useful,
     but WITHOUT ANY WARRANTY; without even the implied warranty of
     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     GNU General Public License for more details.

     You should have received a copy of the GNU General Public License
     along with this program.  If not, see <http://www.gnu.org/licenses/>.

            Jack Elston                       Cory Dixon                        
|           elstonj@colorado.edu              dixonc@colorado.edu              |
|                                                                              |
\*=+--+=#=+--                 --+=#=+--+=#=+--                    --+=#=+--+=#*/

/* Tree View/Tree Store
 *
 * The GtkTreeStore is used to store data in tree form, to be
 * used later on by a GtkTreeView to display it. This demo builds
 * a simple GtkTreeStore and displays it. If you're new to the
 * GtkTreeView widgets and associates, look into the GtkListStore
 * example first.
 *
 */

#include <gtk/gtk.h>
#include "vcConfig.h"
#include "plot_tree.h"
#include "clientList.h"
#include "myStripChart.h"

/*<---Extern Variables---->*/
extern GuiStruct guiStr;

/*<---Global Variables---->*/
static GtkWidget *plot_window = NULL;
static int row_count = 0;

/* columns */
enum
{
	PARAM_COLUMN = 0,
	PLOT_COLUMN,
	PTR_COLUMN,
	TYPE_COLUMN,
	NUM_COLUMNS
};

static 
GtkTreeModel *create_model (void)
{
	GtkTreeStore *model;
	GtkTreeIter iter;

	/* create tree store */
	model = gtk_tree_store_new (NUM_COLUMNS,
	                            G_TYPE_STRING,
	                            G_TYPE_BOOLEAN,
	                            G_TYPE_INT,
	                            G_TYPE_INT);

	//cout << "create_model" << endl;

	/* loop through clients */
	Client * a_client;
	int i = 0;
	while( (a_client = guiStr.shm_ptr->clients.getClient(i++)) != NULL) {
		//cout << "\tclient: " << a_client->name << " state.init=" << (int)a_client->state.init << endl;
		if(a_client->state.init) {
			// create system level tag
			gtk_tree_store_append (model, &iter, NULL);
			gtk_tree_store_set (model, &iter,
			                    PARAM_COLUMN, a_client->name.c_str(),
			                    PLOT_COLUMN, FALSE,
									  PTR_COLUMN, 0,
			                    -1);

			//---------- CMD_TEELM ----------//
			if (a_client->capabilities.find(CMD_TELEM)) 
			{
				//cout << "CMD_TELM" << endl;

				GtkTreeIter child_iter;

				gtk_tree_store_append (model, &child_iter, &iter);
				gtk_tree_store_set (model, &child_iter,
										  PARAM_COLUMN, "GPS-Lat",
										  PLOT_COLUMN, FALSE,
										  PTR_COLUMN, &(a_client->telemetry.gps.pos.lat),
										  TYPE_COLUMN, FLOAT_T,
										  -1);
				gtk_tree_store_append (model, &child_iter, &iter);
				gtk_tree_store_set (model, &child_iter,
										  PARAM_COLUMN, "GPS-Lon",
										  PLOT_COLUMN, FALSE,
										  PTR_COLUMN, &(a_client->telemetry.gps.pos.lon),
										  TYPE_COLUMN, FLOAT_T,
										  -1);
				gtk_tree_store_append (model, &child_iter, &iter);
				gtk_tree_store_set (model, &child_iter,
										  PARAM_COLUMN, "GPS-Track",
										  PLOT_COLUMN, FALSE,
										  PTR_COLUMN, &(a_client->telemetry.gps.track),
										  TYPE_COLUMN, FLOAT_T,
										  -1);
				gtk_tree_store_append (model, &child_iter, &iter);
				gtk_tree_store_set (model, &child_iter,
										  PARAM_COLUMN, "GPS-Alt",
										  PLOT_COLUMN, FALSE,
										  PTR_COLUMN, &(a_client->telemetry.gps.pos.alt),
										  TYPE_COLUMN, FLOAT_T,
										  -1);
				gtk_tree_store_append (model, &child_iter, &iter);
				gtk_tree_store_set (model, &child_iter,
										  PARAM_COLUMN, "GPS-SOG",
										  PLOT_COLUMN, FALSE,
										  PTR_COLUMN, &(a_client->telemetry.gps.sog),
										  TYPE_COLUMN, FLOAT_T,
										  -1);
				gtk_tree_store_append (model, &child_iter, &iter);
				gtk_tree_store_set (model, &child_iter,
										  PARAM_COLUMN, "Airdata-TAS",
										  PLOT_COLUMN, FALSE,
										  PTR_COLUMN, &(a_client->telemetry.airdata.tas),
										  TYPE_COLUMN, FLOAT_T,
										  -1);
				gtk_tree_store_append (model, &child_iter, &iter);
				gtk_tree_store_set (model, &child_iter,
										  PARAM_COLUMN, "Airdata-Alt",
										  PLOT_COLUMN, FALSE,
										  PTR_COLUMN, &(a_client->telemetry.airdata.alt),
										  TYPE_COLUMN, FLOAT_T,
										  -1);
				gtk_tree_store_append (model, &child_iter, &iter);
				gtk_tree_store_set (model, &child_iter,
										  PARAM_COLUMN, "Angles-Roll",
										  PLOT_COLUMN, FALSE,
										  PTR_COLUMN, &(a_client->telemetry.angles.roll),
										  TYPE_COLUMN, INT16_T,
										  -1);
				gtk_tree_store_append (model, &child_iter, &iter);
				gtk_tree_store_set (model, &child_iter,
										  PARAM_COLUMN, "Angles-Pitch",
										  PLOT_COLUMN, FALSE,
										  PTR_COLUMN, &(a_client->telemetry.angles.pitch),
										  TYPE_COLUMN, INT16_T,
										  -1);
				gtk_tree_store_append (model, &child_iter, &iter);
				gtk_tree_store_set (model, &child_iter,
										  PARAM_COLUMN, "Angles-Yaw",
										  PLOT_COLUMN, FALSE,
										  PTR_COLUMN, &(a_client->telemetry.angles.yaw),
										  TYPE_COLUMN, INT16_T,
										  -1);
				//gtk_tree_store_append (model, &child_iter, &iter);
				//gtk_tree_store_set (model, &child_iter,
										  //PARAM_COLUMN, "Navigation-AP",
										  //PLOT_COLUMN, FALSE,
										  //PTR_COLUMN, &(a_client->telemetry.navigation.AP),
										  //TYPE_COLUMN, UINT8_T,
										  //-1);
				gtk_tree_store_append (model, &child_iter, &iter);
				gtk_tree_store_set (model, &child_iter,
										  PARAM_COLUMN, "Navigation-waypt",
										  PLOT_COLUMN, FALSE,
										  PTR_COLUMN, &(a_client->telemetry.navigation.waypt),
										  TYPE_COLUMN, UINT8_T,
										  -1);				
				//gtk_tree_store_append (model, &child_iter, &iter);
				//gtk_tree_store_set (model, &child_iter,
										  //PARAM_COLUMN, "Navigation-OB",
										  //PLOT_COLUMN, FALSE,
										  //PTR_COLUMN, &(a_client->telemetry.navigation.OB),
										  //TYPE_COLUMN, UINT8_T,
										  //-1);
				gtk_tree_store_append (model, &child_iter, &iter);
				gtk_tree_store_set (model, &child_iter,
										  PARAM_COLUMN, "Navigation-value",
										  PLOT_COLUMN, FALSE,
										  PTR_COLUMN, &(a_client->telemetry.navigation.value),
										  TYPE_COLUMN, FLOAT_T,
										  -1);
				gtk_tree_store_append (model, &child_iter, &iter);
				gtk_tree_store_set (model, &child_iter,
										  PARAM_COLUMN, "Navigation-TargetAlt",
										  PLOT_COLUMN, FALSE,
										  PTR_COLUMN, &(a_client->telemetry.navigation.targetAlt),
										  TYPE_COLUMN, FLOAT_T,
										  -1);
				gtk_tree_store_append (model, &child_iter, &iter);
				gtk_tree_store_set (model, &child_iter,
										  PARAM_COLUMN, "Navigation-TargetTAS",
										  PLOT_COLUMN, FALSE,
										  PTR_COLUMN, &(a_client->telemetry.navigation.targetIAS),
										  TYPE_COLUMN, FLOAT_T,
										  -1);
				gtk_tree_store_append (model, &child_iter, &iter);
				gtk_tree_store_set (model, &child_iter,
										  PARAM_COLUMN, "Surfaces-Throttle",
										  PLOT_COLUMN, FALSE,
										  PTR_COLUMN, &(a_client->telemetry.servos.channels[2]),
										  TYPE_COLUMN, UINT16_T,
										  -1);
				gtk_tree_store_append (model, &child_iter, &iter);
				gtk_tree_store_set (model, &child_iter,
										  PARAM_COLUMN, "System-12V",
										  PLOT_COLUMN, FALSE,
										  PTR_COLUMN, &(a_client->telemetry.system.twelveV),
										  TYPE_COLUMN, UINT16_T,
										  -1);
				gtk_tree_store_append (model, &child_iter, &iter);
				gtk_tree_store_set (model, &child_iter,
										  PARAM_COLUMN, "System-5V",
										  PLOT_COLUMN, FALSE,
										  PTR_COLUMN, &(a_client->telemetry.system.fiveV),
										  TYPE_COLUMN, UINT16_T,
										  -1);
				gtk_tree_store_append (model, &child_iter, &iter);
				gtk_tree_store_set (model, &child_iter,
										  PARAM_COLUMN, "System-Unused",
										  PLOT_COLUMN, FALSE,
										  PTR_COLUMN, &(a_client->telemetry.system.availableForCommand),
										  TYPE_COLUMN, INT8_T,
										  -1);

			}
			//---------- CMD_GPS_TELEM ----------//
			else if (a_client->capabilities.find(CMD_GPS_TELEM)) 
			{
				//cout << "CMD_GPS_TELEM" << endl;
				GtkTreeIter child_iter;

				gtk_tree_store_append (model, &child_iter, &iter);
				gtk_tree_store_set (model, &child_iter,
										  PARAM_COLUMN, "GPS-Lat",
										  PLOT_COLUMN, FALSE,
										  PTR_COLUMN, &(a_client->telemetry.gps.pos.lat),
										  TYPE_COLUMN, FLOAT_T,
										  -1);
				gtk_tree_store_append (model, &child_iter, &iter);
				gtk_tree_store_set (model, &child_iter,
										  PARAM_COLUMN, "GPS-Lon",
										  PLOT_COLUMN, FALSE,
										  PTR_COLUMN, &(a_client->telemetry.gps.pos.lon),
										  TYPE_COLUMN, FLOAT_T,
										  -1);
				gtk_tree_store_append (model, &child_iter, &iter);
				gtk_tree_store_set (model, &child_iter,
										  PARAM_COLUMN, "GPS-Track",
										  PLOT_COLUMN, FALSE,
										  PTR_COLUMN, &(a_client->telemetry.gps.track),
										  TYPE_COLUMN, FLOAT_T,
										  -1);
				gtk_tree_store_append (model, &child_iter, &iter);
				gtk_tree_store_set (model, &child_iter,
										  PARAM_COLUMN, "GPS-Alt",
										  PLOT_COLUMN, FALSE,
										  PTR_COLUMN, &(a_client->telemetry.gps.pos.alt),
										  TYPE_COLUMN, FLOAT_T,
										  -1);
				gtk_tree_store_append (model, &child_iter, &iter);
				gtk_tree_store_set (model, &child_iter,
										  PARAM_COLUMN, "GPS-SOG",
										  PLOT_COLUMN, FALSE,
										  PTR_COLUMN, &(a_client->telemetry.gps.sog),
										  TYPE_COLUMN, FLOAT_T,
										  -1);
			}
			//---------- CMD_GPS ----------//
			else if (a_client->capabilities.find(CMD_GPS)) 
			{
				cout << "CMD_GPS" << endl;
				GtkTreeIter child_iter;

				gtk_tree_store_append (model, &child_iter, &iter);
				gtk_tree_store_set (model, &child_iter,
										  PARAM_COLUMN, "GPS-Lat",
										  PLOT_COLUMN, FALSE,
										  PTR_COLUMN, &(a_client->telemetry.gps.pos.lat),
										  TYPE_COLUMN, FLOAT_T,
										  -1);
				gtk_tree_store_append (model, &child_iter, &iter);
				gtk_tree_store_set (model, &child_iter,
										  PARAM_COLUMN, "GPS-Lon",
										  PLOT_COLUMN, FALSE,
										  PTR_COLUMN, &(a_client->telemetry.gps.pos.lon),
										  TYPE_COLUMN, FLOAT_T,
										  -1);
				gtk_tree_store_append (model, &child_iter, &iter);
				gtk_tree_store_set (model, &child_iter,
										  PARAM_COLUMN, "GPS-Alt",
										  PLOT_COLUMN, FALSE,
										  PTR_COLUMN, &(a_client->telemetry.gps.pos.alt),
										  TYPE_COLUMN, FLOAT_T,
										  -1);
			}
			//---------- CMD_GPS_LATLON ----------//
			else if (a_client->capabilities.find(CMD_GPS_LATLON)) 
			{
				cout << "CMD_GPS_LATLON" << endl;
				GtkTreeIter child_iter;

				gtk_tree_store_append (model, &child_iter, &iter);
				gtk_tree_store_set (model, &child_iter,
										  PARAM_COLUMN, "GPS-Lat",
										  PLOT_COLUMN, FALSE,
										  PTR_COLUMN, &(a_client->telemetry.gps.pos.lat),
										  TYPE_COLUMN, FLOAT_T,
										  -1);
				gtk_tree_store_append (model, &child_iter, &iter);
				gtk_tree_store_set (model, &child_iter,
										  PARAM_COLUMN, "GPS-Lon",
										  PLOT_COLUMN, FALSE,
										  PTR_COLUMN, &(a_client->telemetry.gps.pos.lon),
										  TYPE_COLUMN, FLOAT_T,
										  -1);
			}

			//---------- CMD_LINK_STATUS ----------//
			if(a_client->capabilities.find(CMD_LINK_STATUS)) 
			{
				//cout << "CMD_LINK_STATUS" << endl;
				GtkTreeIter child_iter;
				GtkTreeIter link_iter;

				for(int i=0; i < MAX_CLIENTS; i++ ) {
					//cout << "\tclient=" << i << " last_rx=" << a_client->linkstatus[i].last_rx << endl;
					if( a_client->linkstatus[i].last_rx > 0 ) {

						//-- fill in the name of the node --//
						// if we don't know ip, use mac. if ip, check
						// to see if we can get a name from the clien lise
						char idStr[32];
						if( a_client->linkstatus[i].ip[0] == 0 ) {
							sprintf(idStr,"%02X:%02X:%02X:%02X:%02X:%02X",
								a_client->linkstatus[i].mac[0],
								a_client->linkstatus[i].mac[1],
								a_client->linkstatus[i].mac[2],
								a_client->linkstatus[i].mac[3],
								a_client->linkstatus[i].mac[4],
								a_client->linkstatus[i].mac[5]);
						} else {
							sprintf(idStr,"%i.%i.%i.%i",
								a_client->linkstatus[i].ip[0],
								a_client->linkstatus[i].ip[1],
								a_client->linkstatus[i].ip[2],
								a_client->linkstatus[i].ip[3]);

							in_addr addr;
							addr.s_addr = *((in_addr_t *)a_client->linkstatus[i].ip);
							Client * b_client = guiStr.shm_ptr->clients.getClient(addr);
							if( b_client )
								strcpy(idStr, b_client->name.c_str());
						}

						//-- fill in the gtk tree menu --//

						gtk_tree_store_append (model, &child_iter, &iter);
						gtk_tree_store_set (model, &child_iter,
												  PARAM_COLUMN, idStr,
												  PLOT_COLUMN, FALSE,
												  -1);

						gtk_tree_store_append (model, &link_iter, &child_iter);
						gtk_tree_store_set (model, &link_iter,
												  PARAM_COLUMN, "Link-Signal",
												  PLOT_COLUMN, FALSE,
												  PTR_COLUMN, &(a_client->linkstatus[i].signal),
												  TYPE_COLUMN, FLOAT_T,
												  -1);
						gtk_tree_store_append (model, &link_iter, &child_iter);
						gtk_tree_store_set (model, &link_iter,
												  PARAM_COLUMN, "Link-Noise",
												  PLOT_COLUMN, FALSE,
												  PTR_COLUMN, &(a_client->linkstatus[i].noise),
												  TYPE_COLUMN, FLOAT_T,
												  -1);
						gtk_tree_store_append (model, &link_iter, &child_iter);
						gtk_tree_store_set (model, &link_iter,
												  PARAM_COLUMN, "Link-Last RX",
												  PLOT_COLUMN, FALSE,
												  PTR_COLUMN, &(a_client->linkstatus[i].last_rx),
												  TYPE_COLUMN, FLOAT_T,
												  -1);
						gtk_tree_store_append (model, &link_iter, &child_iter);
						gtk_tree_store_set (model, &link_iter,
												  PARAM_COLUMN, "Channel Cap",
												  PLOT_COLUMN, FALSE,
												  PTR_COLUMN, &(a_client->linkstatus[i].channelCap),
												  TYPE_COLUMN, FLOAT_T,
												  -1);
						gtk_tree_store_append (model, &link_iter, &child_iter);
						gtk_tree_store_set (model, &link_iter,
												  PARAM_COLUMN, "Bytes TX",
												  PLOT_COLUMN, FALSE,
												  PTR_COLUMN, &(a_client->linkstatus[i].numBytesTx),
												  TYPE_COLUMN, UINT32_T,
												  -1);
						gtk_tree_store_append (model, &link_iter, &child_iter);
						gtk_tree_store_set (model, &link_iter,
												  PARAM_COLUMN, "Bytes RX",
												  PLOT_COLUMN, FALSE,
												  PTR_COLUMN, &(a_client->linkstatus[i].numBytesRx),
												  TYPE_COLUMN, UINT32_T,
												  -1);
						gtk_tree_store_append (model, &link_iter, &child_iter);
						gtk_tree_store_set (model, &link_iter,
												  PARAM_COLUMN, "Rate TX",
												  PLOT_COLUMN, FALSE,
												  PTR_COLUMN, &(a_client->linkstatus[i].rateTx),
												  TYPE_COLUMN, FLOAT_T,
												  -1);
						gtk_tree_store_append (model, &link_iter, &child_iter);
						gtk_tree_store_set (model, &link_iter,
												  PARAM_COLUMN, "Rate RX",
												  PLOT_COLUMN, FALSE,
												  PTR_COLUMN, &(a_client->linkstatus[i].rateRx),
												  TYPE_COLUMN, FLOAT_T,
												  -1);

					}
				}
			}
			//---------- CMD_FLIGHT_COMPUTER ----------//
				//if (a_client->capabilities.find(CMD_FLIGHT_COMPUTER))
			//---------- CMD_AUTOPILOT ----------//
				//if (a_client->capabilities.find(CMD_AUTOPILOT))

		}
	}

	return GTK_TREE_MODEL (model);
}

static void
item_toggled (GtkCellRendererToggle *cell,
				gchar                 *path_str,
				gpointer               data)
{
	GtkTreeModel *model = (GtkTreeModel *)data;
	GtkTreePath *path = gtk_tree_path_new_from_string (path_str);
	GtkTreeIter iter;
	gboolean toggle_item;

	gint *column;

	column = (gint *)g_object_get_data (G_OBJECT (cell), "column");

	/* get toggled iter */
	gtk_tree_model_get_iter (model, &iter, path);
	gtk_tree_model_get (model, &iter, column, &toggle_item, -1);

	/* do something with the value */
	toggle_item ^= 1;

	/* set new value */
	gtk_tree_store_set (GTK_TREE_STORE (model), &iter, column, toggle_item, -1);

	GtkTreeIter child_iter;
	gboolean valid;
	if( gtk_tree_model_iter_has_child( model, &iter ) ) {
		valid = gtk_tree_model_iter_children( model, &child_iter, &iter);
		while (valid) {
			gtk_tree_store_set (GTK_TREE_STORE (model), &child_iter, column, toggle_item, -1);
			valid = gtk_tree_model_iter_next (model, &child_iter);
		}
	}
	
	//printf("item_toggled: path=%s value=%i\n", path_str, toggle_item);

	/* clean up */
	gtk_tree_path_free (path);
}

static void
add_columns (GtkTreeView *treeview)
{
	gint col_offset;
	GtkCellRenderer *renderer;
	GtkTreeModel *model = gtk_tree_view_get_model (treeview);

	/* column for system parameter names */
	renderer = gtk_cell_renderer_text_new ();
	g_object_set (renderer, "xalign", 0.0, NULL);

	col_offset = gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (treeview),
									-1, "Parameter",
									renderer, "text",
									PARAM_COLUMN,
									NULL);

	/* plot column */
	renderer = gtk_cell_renderer_toggle_new ();
	g_object_set (renderer, "xalign", 1.0, NULL);
	g_object_set_data (G_OBJECT (renderer), "column", (gint *)PLOT_COLUMN);

	g_signal_connect (renderer, "toggled", G_CALLBACK (item_toggled), model);

	col_offset = gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (treeview),
									-1, "Plot",
									renderer, 
									"active",
									PLOT_COLUMN,
									NULL);
}

GtkWidget * create_param_window ( )
{
	GtkWidget  *treeview = NULL;
	GtkTreeModel *model;

	if (!plot_window)
	{
		//cout << "create_param_window()" << endl;
		if( guiStr.builder == NULL ) {
			cout << "create_param_window() - no builder for gui" << endl;
			return NULL;
		}

		// create window, etc 
		plot_window = GTK_WIDGET (gtk_builder_get_object (guiStr.builder, "paramWindow"));
	}
	GtkWidget *sw = GTK_WIDGET (gtk_builder_get_object (guiStr.builder, "vsw"));
	GtkWidget *apply_button = GTK_WIDGET (gtk_builder_get_object (guiStr.builder, "applyButton"));
	GtkWidget *cancel_button = GTK_WIDGET (gtk_builder_get_object (guiStr.builder, "cancelButton"));

	if (GTK_WIDGET_VISIBLE (plot_window)) {
		gtk_widget_hide(plot_window);
		return plot_window;
	}

	// clear the contents of the container
	GList* childList = gtk_container_get_children(GTK_CONTAINER (sw));
	if( childList ) {
		gtk_widget_destroy(GTK_WIDGET(g_list_nth_data(childList, 0) ) );
	}

	// create model 
	model = create_model ();

	// create tree view 
	treeview = gtk_tree_view_new_with_model (model);
	g_object_unref (model);

	// setup tree functionality
	gtk_tree_view_set_rules_hint (GTK_TREE_VIEW (treeview), TRUE);
	gtk_tree_selection_set_mode (gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview)), GTK_SELECTION_MULTIPLE);

	// draw the columns
	add_columns (GTK_TREE_VIEW (treeview));

	// add to container
	gtk_container_add (GTK_CONTAINER (sw), treeview);

	// callbacks / signals
	g_signal_connect (GTK_OBJECT(plot_window), "delete_event", G_CALLBACK(plot_window_destroy), plot_window);
	g_signal_connect (GTK_OBJECT(apply_button), "clicked", G_CALLBACK (plot_button_clicked), model);
	g_signal_connect (GTK_OBJECT(cancel_button), "clicked", G_CALLBACK (plot_button_clicked), NULL);

	gtk_widget_show_all (plot_window);
	return plot_window;
}

void plot_button_clicked(GtkWidget *w, gpointer user_data)
{
	//printf( " -- plot_button_clicked -- \n");

	GtkTreeModel *model = (GtkTreeModel *)user_data;
	GtkTreeIter   sys_iter;
	gboolean      valid;
	String        plotName;
	DataSet       data;

	// hide the window, it is not destroyed
	gtk_widget_hide(plot_window);

	// if we don't have a model, the cancel button was hit
	if( !GTK_IS_TREE_MODEL (model) ) {
		return;
	}

	/* Get the first iter in the list */
	valid = gtk_tree_model_get_iter_first (model, &sys_iter);

	/* Walk through the list, reading each row */
	row_count = -1;
	plotName = tree_parse( model, sys_iter, data );

	if( data.setNum > 0 )
		create_plot_window(plotName, data.setNum, data.setNames, data.setPtr, data.setType);	

	for( int i=0; i < data.setNum; i++)
		if( data.setNames[i] ) 
			delete [] data.setNames[i];
}

String tree_parse( GtkTreeModel *model, GtkTreeIter &iter, DataSet &data  )
{
	GtkTreeIter  child_iter;
	gboolean     valid = false;
	gchar	      *sys_name = NULL;
	gboolean     do_plot = false;
	gint         ptr_data = 0;
	gint         data_type;
	String       plotName;
	gboolean     system = false;
	
	// get data from current row
	gtk_tree_model_get (model, &iter, 
							  PARAM_COLUMN, &sys_name,
							  PLOT_COLUMN, &do_plot,
							  PTR_COLUMN, &ptr_data,
							  TYPE_COLUMN, &data_type,
							  -1);
	//cout << "name: " << sys_name << endl;
	
	row_count++;
	if( ptr_data == 0 )
		system = true;

	int tmpNum = data.setNum;

	if( gtk_tree_model_iter_has_child( model, &iter ) ) 
	{
		//cout << "has child" << endl;
		valid = gtk_tree_model_iter_children( model, &child_iter, &iter);

		if( valid )
			plotName += tree_parse( model, child_iter, data);

		if( system & (tmpNum < data.setNum) ) 
			plotName = sys_name + String(" => ") + plotName;

	} else {
		/* Do something with the data */
		//g_print ("Row %d: (%s,%d,%p)", row_count, sys_name, do_plot, (void *)ptr_data);
		//if( ptr_data != 0 ) printf(" - val: %f\n", *((float *)ptr_data));
		//else printf("\n");

		if( do_plot ) 
		{
			data.setNames[data.setNum] = new char[64];
			sprintf(data.setNames[data.setNum], "%s", sys_name);
			data.setPtr[data.setNum] = (void *)ptr_data;
			data.setType[data.setNum] = data_type;
			data.setNum++;

			if( strlen(sys_name) > 0 ) {
				plotName += " => ";
				plotName += sys_name;
			}
		}

	}

	valid = gtk_tree_model_iter_next (model, &iter);
	if( valid ) {
		//cout << "next iter " << endl;
		plotName += tree_parse( model, iter, data);
	}

	g_free (sys_name);
	return plotName;
}

void create_plot_window(String plotName, int setNum, char *setNames[], void * setPtr[], int setType[])	
{
	// local copy of numberof created windows
	static uint32_t chartID = 0;

	GtkStripChart * cpu_graph;
	gchar window_name[256];
	sprintf(window_name,"Plot %i", chartID);
	chartID++;

	// create window, etc 
	GtkWidget *window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
	gtk_window_set_resizable(GTK_WINDOW(window),TRUE);

	gtk_window_set_title (GTK_WINDOW (window), window_name);
	g_signal_connect (window, "destroy", G_CALLBACK (gtk_widget_destroyed), &window);

	GtkWidget * vbox;
	vbox = gtk_vbox_new (FALSE, 8);
	gtk_container_set_border_width (GTK_CONTAINER (vbox), 8);
	gtk_container_add (GTK_CONTAINER (window), vbox);

	// add plot name
	gtk_box_pack_start (GTK_BOX (vbox), gtk_label_new (plotName.c_str()), FALSE, FALSE, 0);

	// graph
	cpu_graph = gtkstripchart_new (setNum, (const gchar**)setNames, setPtr, setType);
	cpu_graph->parent = window;

	gtk_box_pack_start (GTK_BOX (vbox), cpu_graph->main_widget, TRUE, TRUE, 0);
	gtk_container_set_border_width (GTK_CONTAINER (cpu_graph->main_widget), GNOME_PAD_SMALL);

	gtkstripchart_start (cpu_graph);

	gtk_window_set_default_size(GTK_WINDOW (window), cpu_graph->config.width, cpu_graph->config.height);
	gtk_container_set_resize_mode(GTK_CONTAINER(window), GTK_RESIZE_IMMEDIATE);

	gtk_widget_show_all (window);
}

// If you return FALSE in the "delete_event" signal handler, GTK will emit
// the "destroy" signal. Returning TRUE means you don't want the window to be
// destroyed.  This is useful for popping up 'are you sure you want to quit?'
// type dialogs.
gboolean plot_window_destroy(GtkWidget * widget, GdkEventKey * event, gpointer user_data)
{
	if( user_data == plot_window) {
		gtk_widget_hide_all (plot_window);
		return TRUE;
	}
	return FALSE;
}
